package lesson5.example1;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;

public class MyTransformer implements ClassFileTransformer {

	public byte[] transform(
			ClassLoader loader, 
			String className, 
			Class<?> classBeingRedefined,
			ProtectionDomain protectionDomain, 
			byte[] classfileBuffer ) throws IllegalClassFormatException {

		ClassReader cr = new ClassReader(classfileBuffer);
		ClassNode classNode = new ClassNode(Opcodes.ASM6);
		cr.accept(classNode, ClassReader.SKIP_FRAMES);

		for (MethodNode methodNode : classNode.methods) {
			if ("main".equals(methodNode.name)) {
				InsnList instrumentation = new InsnList();
				instrumentation
						.add(new FieldInsnNode(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"));
				instrumentation.add(new LdcInsnNode("Hello, Instrumentation!"));
				instrumentation.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println",
						"(Ljava/lang/String;)V", false));

				methodNode.instructions.insert(instrumentation);
				break;
			}
		}

		ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
		classNode.accept(cw);
		return cw.toByteArray();
	}
}
